﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RVEAd.Business.Model;
using System.Diagnostics;
using System.Data.Objects;
using System.Data;

namespace RVEAd.Business
{
    public class RveBL
    {
        #region .ctor
        public RveBL()
        {

        }
        #endregion


        #region Client

        public List<Client> GetClients()
        {
            using (var ctx = new RVEAdsEntities())
            {
                return ctx.GetAllClients();
            }
        }

        public List<Client> GetClientsStartWith(string nume)
        {
            using (var ctx = new RVEAdsEntities())
            {

                IQueryable<Client> query;

                if (!string.IsNullOrEmpty(nume))
                {
                    query =
                        from c in ctx.Clients
                        where c.Nume.Contains(nume)
                        orderby c.Nume ascending
                        select c;
                }
                else
                {
                    query =
                        from c in ctx.Clients
                        orderby c.Nume ascending
                        select c;
                }

                return query.ToList();
            }
        }

        public void AddClient(string clientName, int idCategory)
        {
            using (var ctx = new RVEAdsEntities())
            {
                ctx.AddClient(clientName, idCategory);
                ctx.SaveChanges();
            }
        }

        public void UpdateClient(Client client, int idCategory)
        {
            using (var ctx = new RVEAdsEntities())
            {
                ctx.UpdateClient(client, idCategory);
                ctx.SaveChanges();
            }
        }

        public void DeleteClient(int id)
        {
            using (var ctx = new RVEAdsEntities())
            {
                ctx.DeleteClient(id);
                ctx.SaveChanges();
            }
        }

        #endregion

        #region Client Ads
        /// <summary>
        /// Get client ads
        /// </summary>
        /// <param name="clientId"></param>
        /// <param name="date"></param>
        /// <returns></returns>
        public List<ClientAd> GetClientAds(int clientId, DateTime date)
        {
            using (var ctx = new RVEAdsEntities())
            {
                return ctx.GetClientAds(clientId, date);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="clientId"></param>
        /// <param name="date"></param>
        /// <param name="spotFilename"></param>
        /// <param name="broadcastNo"></param>
        public void CreateCliendAd(int clientId, DateTime date, string spotFilename, int broadcastNo)
        {
            using (var ctx = new RVEAdsEntities())
            {
                ctx.CreateClientAd(clientId, date, spotFilename, broadcastNo);
                ctx.SaveChanges();
            }
        }

        #endregion

        #region Plan Ads

        public IEnumerable<AdPlan> GetPlanForExport(int year, int month, int clientId)
        {
            using (var ctx = new RVEAdsEntities())
            {

                if (clientId > 0)
                {
                    var queryPlan = from plan in ctx.AdPlans
                                        .Include("ClientAd")
                                        .Include("ClientAd.Client")
                                        .Include("ClientAd.Client.ClientCategory")

                                    where
                                        plan.PlanDate.Year == year &&
                                        plan.PlanDate.Month == month &&
                                        plan.ClientAd.Client.ID == clientId

                                    orderby plan.PlanDate.Day
                                    select plan;

                    return queryPlan.ToList();
                }


                var queryPlanAlClients = from plan in ctx.AdPlans
                                           .Include("ClientAd")
                                           .Include("ClientAd.Client")
                                           .Include("ClientAd.Client.ClientCategory")

                                         where
                                             plan.PlanDate.Year == year &&
                                             plan.PlanDate.Month == month

                                         orderby plan.PlanDate.Day
                                         select plan;

                return queryPlanAlClients.ToList();
            }
        }

        public List<Model.AdPlanModel> GetAdPlans(DateTime data)
        {
            using (var ctx = new RVEAdsEntities())
            {
                var queryEntities = from plan in ctx.AdPlans.Include("ClientAd").Include("ClientAd.Client").Include("ClientAd.Client.ClientCategory")
                                    where
                                        plan.PlanDate.Year == data.Year &&
                                        plan.PlanDate.Month == data.Month &&
                                        plan.PlanDate.Day == data.Day
                                    orderby plan.ClientAd.Client.Nume, plan.ClientAd.FileName ascending
                                    select plan;

                var query = from i in queryEntities.ToList()
                            select new AdPlanModel
                            {
                                AdPlanId = i.ID,
                                CliendAdId = i.ClientAd.ID,
                                ClientId = i.ClientAd.Client.ID,
                                ClientName = i.ClientAd.Client.Nume,
                                CategoryName = i.ClientAd.Client.ClientCategory.Category,
                                BroadcastNo = i.ClientAd.BroadcastNo,
                                SpotName = i.ClientAd.FileName,
                                Data = i.PlanDate,
                                AM1 = i.AM1.ToString(),
                                AM2 = i.AM2.ToString(),
                                AM3 = i.AM3.ToString(),
                                PM1 = i.PM1.ToString(),
                                PM2 = i.PM2.ToString(),
                            };

                return query.ToList();
            }
        }
        public List<Model.AdPlanModel> GetAdPlans(int year, int month, int planId)
        {
            using (var ctx = new RVEAdsEntities())
            {
                var queryEntities = from plan in ctx.AdPlans.Include("ClientAd").Include("ClientAd.Client")
                                    where
                                        plan.PlanDate.Year == year &&
                                        plan.PlanDate.Month == month &&
                                        plan.ClientAd.ID == planId
                                    orderby plan.PlanDate ascending
                                    select plan;

                var query = from i in queryEntities.ToList()
                            select new AdPlanModel
                            {
                                AdPlanId = i.ID,
                                CliendAdId = i.ClientAd.ID,
                                ClientId = i.ClientAd.Client.ID,
                                ClientName = i.ClientAd.Client.Nume,
                                BroadcastNo = i.ClientAd.BroadcastNo,
                                Data = i.PlanDate,
                                AM1 = i.AM1.ToString(),
                                AM2 = i.AM2.ToString(),
                                AM3 = i.AM3.ToString(),
                                PM1 = i.PM1.ToString(),
                                PM2 = i.PM2.ToString(),
                            };

                return query.ToList();
            }
        }
        public void SetIntervalInAdPlan(int planId, bool value, IntervalEnum interval)
        {
            using (var ctx = new RVEAdsEntities())
            {
                var plan = ctx.AdPlans
                    .Where(p => p.ID == planId)
                    .FirstOrDefault();

                if (plan != null)
                {
                    switch (interval)
                    {
                        case IntervalEnum.AM1:
                            plan.AM1 = value;
                            break;
                        case IntervalEnum.AM2:
                            plan.AM2 = value;
                            break;
                        case IntervalEnum.AM3:
                            plan.AM3 = value;
                            break;
                        case IntervalEnum.PM1:
                            plan.PM1 = value;
                            break;
                        case IntervalEnum.PM2:
                            plan.PM2 = value;
                            break;
                    }

                    ctx.SaveChanges();
                }
            }
        }

        private int CountPlanningPerDayAndInterval(IntervalEnum invervalEnum, DateTime data, int idClientAd)
        {

            var start = Stopwatch.StartNew();
            start.Start();

            int planCount = 0;

            using (var ctx = new RVEAdsEntities())
            {
                switch (invervalEnum)
                {
                    case IntervalEnum.AM1:
                        planCount = ctx.MyIntervalCount(data, "AM1").FirstOrDefault() ?? 0;
                        break;
                    case IntervalEnum.AM2:
                        planCount = ctx.MyIntervalCount(data, "AM2").FirstOrDefault() ?? 0;
                        break;
                    case IntervalEnum.AM3:
                        planCount = ctx.MyIntervalCount(data, "AM3").FirstOrDefault() ?? 0;
                        break;
                    case IntervalEnum.PM1:
                        planCount = ctx.MyIntervalCount(data, "PM1").FirstOrDefault() ?? 0;
                        break;
                    case IntervalEnum.PM2:
                        planCount = ctx.MyIntervalCount(data, "PM2").FirstOrDefault() ?? 0;
                        break;
                }
            }

            start.Stop();
            Debug.WriteLine(start.Elapsed + " " + invervalEnum.ToString());

            return planCount;
        }
        private int GetTrueFlagsCountPerMonth(int idClientAd)
        {
            int count = 0;

            using (var ctx = new RVEAdsEntities())
            {
                var query = (from plan in ctx.AdPlans.Include("ClientAd")
                             where plan.ClientAd.ID == idClientAd
                             select plan).ToList();

                foreach (var item in query)
                {
                    count = count + CountTrueFlags(item);
                }

                return count;
            }
        }
        private int GetTrueFlagsCountPerDay(int idAdPlan)
        {
            return CountTrueFlags(GetAdPlan(idAdPlan));
        }
        private int CountTrueFlags(AdPlan adPlan)
        {
            int count = 0;

            if (adPlan.AM1)
            {
                count++;
            }

            if (adPlan.AM2)
            {
                count++;
            }

            if (adPlan.AM3)
            {
                count++;
            }

            if (adPlan.PM1)
            {
                count++;
            }

            if (adPlan.PM2)
            {
                count++;
            }

            return count;
        }
        private AdPlan GetAdPlan(int id)
        {
            using (var ctx = new RVEAdsEntities())
            {
                return ctx.AdPlans.Where(p => p.ID == id).FirstOrDefault();
            }
        }

        #endregion

        #region Category

        public List<ClientCategory> GetAllCategories()
        {
            using (var ctx = new RVEAdsEntities())
            {
                return ctx.ClientCategories.OrderBy(c => c.Category).ToList();
            }
        }

        public void AddCategory(string description)
        {
            using (var ctx = new RVEAdsEntities())
            {
                ctx.AddToClientCategories(new ClientCategory { Category = description });
                ctx.SaveChanges();
            }
        }

        public void UpdateCategory(ClientCategory category)
        {
            using (var ctx = new RVEAdsEntities())
            {
                var currentCategory = ctx.ClientCategories
                    .Where(c => c.ID == category.ID)
                    .FirstOrDefault();

                if (currentCategory != null)
                {
                    currentCategory.Category = category.Category;
                }

                ctx.SaveChanges();
            }
        }

        public void DeleteCategory(int idCategory)
        {
            using (var ctx = new RVEAdsEntities())
            {
                try
                {
                    var currentCategory = ctx.ClientCategories
                       .Where(c => c.ID == idCategory)
                       .FirstOrDefault();

                    ctx.ClientCategories.DeleteObject(currentCategory);
                    ctx.SaveChanges();
                }
                catch (Exception ex)
                {
                    throw new Exception("Aceasta categorie nu se poate sterge !");
                }
            }
        }
        #endregion

        #region Live Summary

        public DaySummaryModel GetPlanSummary(AdPlanModel adPlan, DateTime date)
        {
            using (var ctx = new RVEAdsEntities())
            {

                // count true flags for current plan (selected day)
                int clientPerDay = GetTrueFlagsCountPerDay(adPlan.AdPlanId);

                // count true flags for current month
                int clientPerMonth = GetTrueFlagsCountPerMonth(adPlan.CliendAdId);

                DaySummaryModel summary = new DaySummaryModel
                {
                    ClientName = adPlan.ClientName,
                    SpotName = adPlan.SpotName,

                    PlanContract = adPlan.BroadcastNo.ToString(),
                    PlanMonth = clientPerMonth.ToString(),
                    PlanDay = clientPerDay.ToString(),

                };

                return summary;
            }
        }

        public DaySummaryModel GetLiveSummary(AdPlanModel adPlan, DateTime date)
        {
            /*
             * Status Client = number of True (X) on AM1..PM2
             * Status Client / Selected Day
             * Status Client / Selected Month
             * Number of broadcasts
             * 
             */

            using (var ctx = new RVEAdsEntities())
            {

                // count true flags for current plan (selected day)
                int clientPerDay = GetTrueFlagsCountPerDay(adPlan.AdPlanId);

                // count true flags for current month
                int clientPerMonth = GetTrueFlagsCountPerMonth(adPlan.CliendAdId);

                DaySummaryModel summary = new DaySummaryModel
                {
                    ClientName = adPlan.ClientName,
                    SpotName = adPlan.SpotName,

                    PlanContract = adPlan.BroadcastNo.ToString(),
                    PlanMonth = clientPerMonth.ToString(),
                    PlanDay = clientPerDay.ToString(),

                    PlanAM1 = CountPlanningPerDayAndInterval(IntervalEnum.AM1, date, adPlan.CliendAdId).ToString(),
                    PlanAM2 = CountPlanningPerDayAndInterval(IntervalEnum.AM2, date, adPlan.CliendAdId).ToString(),
                    PlanAM3 = CountPlanningPerDayAndInterval(IntervalEnum.AM3, date, adPlan.CliendAdId).ToString(),
                    PlanPM1 = CountPlanningPerDayAndInterval(IntervalEnum.PM1, date, adPlan.CliendAdId).ToString(),
                    PlanPM2 = CountPlanningPerDayAndInterval(IntervalEnum.PM2, date, adPlan.CliendAdId).ToString()
                };

                return summary;

                //StringBuilder stringBuilder = new StringBuilder();

                //stringBuilder.AppendLine(string.Format("Detalii pentru             \t\t {0}", adPlan.ClientName));
                //stringBuilder.AppendLine(string.Format("Spot                       \t\t {0}", adPlan.SpotName.Trim()));
                //stringBuilder.AppendLine();

                //stringBuilder.AppendLine(string.Format("Total planificari / zi:    \t\t {0}", clientPerDay));
                //stringBuilder.AppendLine(string.Format("Total planificari / luna:  \t\t {0}", clientPerMonth));
                //stringBuilder.AppendLine();

                //stringBuilder.AppendLine(string.Format("Planificari din contract:  \t\t {0}", adPlan.BroadcastNo));

                //stringBuilder.AppendLine();
                //stringBuilder.AppendLine(string.Format("Total/Zi/AM1:              \t\t {0}", CountPlanningPerDayAndInterval(IntervalEnum.AM1, date)));
                //stringBuilder.AppendLine(string.Format("Total/Zi/AM2:              \t\t {0}", CountPlanningPerDayAndInterval(IntervalEnum.AM2, date)));
                //stringBuilder.AppendLine(string.Format("Total/Zi/AM3:              \t\t {0}", CountPlanningPerDayAndInterval(IntervalEnum.AM3, date)));
                //stringBuilder.AppendLine(string.Format("Total/Zi/PM1:              \t\t {0}", CountPlanningPerDayAndInterval(IntervalEnum.PM1, date)));
                //stringBuilder.AppendLine(string.Format("Total/Zi/PM2:              \t\t {0}", CountPlanningPerDayAndInterval(IntervalEnum.PM2, date)));

                //return stringBuilder.ToString();
            }


        }

        #endregion

    }
}
